//
//  XY_View.m
//  V3d_Cocoa
//
//  Created by Y my on 11-3-16.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#import "XY_View.h"


@implementation XY_View

- (id)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code here.
		NSLog(@"Init XY view OK!");
    }
    return self;
}

- (void)awakeFromNib {
	[self updateView];
}

- (void)getSpecificData {
	self.infoString = [NSString stringWithFormat:@"XY"];
	
	// get xy images from mainViewData and my4DImage
	//Ctype = mainViewData.ctype; //set how to display RGB color.
	CGFloat tmpRatio = mainViewData.curFocusZratio;
	b_displayFocusCrossLine = mainViewData.bDrawFocusCrossLine;
	
	if (tmpRatio == cur_focus_ratio && Ctype == mainViewData.ctype && [self translationEqual:mainViewData.xytranslation] && zoom_scale == mainViewData.xzoom_scale) {
		return;
	}
	if(mainViewData.ctype == colorUnknown)
	{
		switch ([my4DImage cDim]) {
			case 1:
				mainViewData.ctype = colorGray;
				break;
			case 3:
				mainViewData.ctype = colorRGB;
				break;
			default:
				mainViewData.ctype = colorGray;
				break;
		}
	}
	cur_focus_ratio = tmpRatio;
	Ctype = mainViewData.ctype;
	zoom_scale = mainViewData.xzoom_scale;
	[self setTranslation:mainViewData.xytranslation];
	[self internal_only_imgplane_op];
}

- (void)pinch:(UIPinchGestureRecognizer *)gesture
{
	if((gesture.state == UIGestureRecognizerStateChanged) ||
	   (gesture.state == UIGestureRecognizerStateEnded))
	{
		mainViewData.xzoom_scale *= gesture.scale;
		gesture.scale = 1;
	}
}


- (void)pan:(UIPanGestureRecognizer *)recognizer
{
	
	if(zoom_scale > 1)
	{		
		if((recognizer.state == UIGestureRecognizerStateChanged) || (recognizer.state == UIGestureRecognizerStateEnded))
		{
			
			CGPoint tranlate = [recognizer translationInView:self];
			[mainViewData setXytranslation:tranlate];
			
			if(mainViewData.xytranslation.x > [self bounds].size.width * (zoom_scale - 1) / 2)
				[mainViewData setXytranslationX:([self bounds].size.width * (zoom_scale - 1) / 2)];
			else if(mainViewData.xytranslation.x < -[self bounds].size.width * (zoom_scale - 1) / 2)
				[mainViewData setXytranslationX:(-[self bounds].size.width * (zoom_scale - 1) / 2)];
			if(mainViewData.xytranslation.y > [self bounds].size.height * (zoom_scale - 1) /2)
				[mainViewData setXytranslationY:([self bounds].size.height * (zoom_scale - 1) /2)];
			else if(mainViewData.xytranslation.y < -[self bounds].size.height * (zoom_scale - 1) /2)
				[mainViewData setXytranslationY:(-[self bounds].size.height * (zoom_scale - 1) /2)];
			
			[recognizer setTranslation:CGPointZero inView:self];
			[self updateView];								
		}
		
	}
}
  
   
- (BOOL)getFocusCrossLinePosWidth:(int*)focusPosInWidth andHeight:(int*)focusPosInHeight {
	
	if (self.mainViewData == nil)
		return NO;

	CGSize size = [self bounds].size;
	*focusPosInWidth = self.mainViewData.curFocusXratio * size.width;
	*focusPosInHeight = self.mainViewData.curFocusYratio * size.height;
	
	return (*focusPosInWidth > -1 && *focusPosInHeight > -1);
}
/*
- (CGImageRef)fillPixmapWithRawData_colormap:(unsigned char****)p4d
								 dtype:(ImagePixelType)dtype
								   sz0:(V3DLONG)sz0
								   sz1:(V3DLONG)sz1
								   sz2:(V3DLONG)sz2
								   sz3:(V3DLONG)sz3
							 cposRatio:(CGFloat)cposRatio
							  colorMap:(ColorMap*)pc
{
	
	NSBitmapImageRep* tmpimg = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL
																	   pixelsWide:sz0
																	   pixelsHigh:sz1
																	bitsPerSample:8
																  samplesPerPixel:3
																		 hasAlpha:NO
																		 isPlanar:NO
																   colorSpaceName:@"NSCalibratedRGBColorSpace"
																	  bytesPerRow:sz0*4
																	 bitsPerPixel:32];
	[tmpimg autorelease];
	
	
	
	
	if (!p4d || !pc)
	{
		NSLog(@"The input parameters are invalid in fillPixmapWithRawData_zPlanes_colormap()!");
		return [tmpimg CGImage];
	}
	
	if (sz3<1)
	{
		NSLog(@"The number of color channels cannot be smalled than 1. Note that as an indexed color, only the first (0-th) dim is used.");
		return [tmpimg CGImage];
	}
	
	//QImage tmpimg = QImage(sz0, sz1, QImage::Format_RGB32);
	int tr,tg,tb;
	int clen = pc.len;
	V3DLONG ind;
	
	V3DLONG curpos = (cposRatio>1)?sz2-1:(cposRatio * sz2 - 1);
	curpos = (curpos<0)?0:curpos;
	
	V3DLONG i,j;
	
	float ***p3d_float32;
	unsigned short ***p3d_uint16;
	unsigned char ***p3d_uint8;
	
	unsigned char* tmpData = [tmpimg bitmapData];
	NSUInteger bytesPerRow = sz0 * 4;
	switch (dtype)
	{
		case V3D_UINT8:
			p3d_uint8 = (unsigned char ***)(p4d[0]);
			
			for (j=0;j<sz1;j++)
			{
				for (i=0;i<sz0;i++)
				{
					ind = (V3DLONG)(p3d_uint8[curpos][j][i]);
					if (ind>=clen) ind = ind % clen;
					tr = pc.map2d[ind][0];
					tg = pc.map2d[ind][1];
					tb = pc.map2d[ind][2];
					tmpData[j * bytesPerRow + i * 4] = tr;
					tmpData[j * bytesPerRow + i * 4 + 1] = tg;
					tmpData[j * bytesPerRow + i * 4 + 2] = tb;
					tmpData[j * bytesPerRow + i * 4 + 3] = 0;
				}
			}
			break;
			
		case V3D_UINT16:
			p3d_uint16 = (unsigned short ***)(p4d[0]);
			
			for (j=0;j<sz1;j++)
			{
				for (i=0;i<sz0;i++)
				{
					ind = (V3DLONG)(p3d_uint16[curpos][j][i]);
					if (ind>=clen) ind = ind % clen;
					tr = pc.map2d[ind][0];
					tg = pc.map2d[ind][1];
					tb = pc.map2d[ind][2];
					tmpData[j * bytesPerRow + i * 4] = tr;
					tmpData[j * bytesPerRow + i * 4 + 1] = tg;
					tmpData[j * bytesPerRow + i * 4 + 2] = tb;
					tmpData[j * bytesPerRow + i * 4 + 3] = 0;
				}
			}
			break;
			
		case V3D_FLOAT32:
			p3d_float32 = (float ***)(p4d[0]);
			
			for (j=0;j<sz1;j++)
			{
				for (i=0;i<sz0;i++)
				{
					ind = (V3DLONG)(fabs(p3d_float32[curpos][j][i]));
					if (ind>=clen) ind = ind % clen;
					tr = pc.map2d[ind][0];
					tg = pc.map2d[ind][1];
					tb = pc.map2d[ind][2];
					tmpData[j * bytesPerRow + i * 4] = tr;
					tmpData[j * bytesPerRow + i * 4 + 1] = tg;
					tmpData[j * bytesPerRow + i * 4 + 2] = tb;
					tmpData[j * bytesPerRow + i * 4 + 3] = 0;
				}
			}
			break;
			
		default:
			break;
	}
	
	return [tmpimg CGImage];
}
*/

- (CGImageRef)fillPixmapWithRawData:(unsigned char****)p4d
						  sz0:(V3DLONG)sz0
						  sz1:(V3DLONG)sz1
						  sz2:(V3DLONG)sz2
						  sz3:(V3DLONG)sz3
						ctype:(ImageDisplayColorType)ctype
					cposRatio:(CGFloat)cposRatio
			 intensityRescale:(BOOL)bIntensityRescale
					   p_vmax:(double*)p_vmax
					   p_vmin:(double*)p_vmin
{
	//QImage tmpimg = QImage(sz0, sz1, QImage::Format_RGB32);
	/*
	NSBitmapImageRep* tmpimg = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL
																	   pixelsWide:sz0
																	   pixelsHigh:sz1
																	bitsPerSample:8
																  samplesPerPixel:3
																		 hasAlpha:NO
																		 isPlanar:NO
																   colorSpaceName:@"NSCalibratedRGBColorSpace"
																	  bytesPerRow:sz0*4
																	 bitsPerPixel:32];
	[tmpimg autorelease];
	*/
	
	unsigned char tr = 0,tg = 0,tb = 0;
	unsigned char* tmpData = malloc(sz0*sz1*4*sizeof(unsigned char));
	V3DLONG curpos = (cposRatio>1)?sz2-1:(cposRatio * sz2 - 1);
	curpos = (curpos<0)?0:curpos;
	
	/*
	 unsigned char **p2dRed, **p2dGreen, **p2dBlue;
	 p2dBlue = (sz3<3) ? 0 : (unsigned char **)(p4d[2][curpos]);
	 p2dGreen = (sz3<2) ? 0 : (unsigned char **)(p4d[1][curpos]);
	 p2dRed = (sz3<1) ? 0 : (unsigned char **)(p4d[0][curpos]);
	 */
	
	V3DLONG i,j;
	double tmpr = 255,tmpg = 255,tmpb = 255;
	double tmpr_min = 0, tmpg_min = 0, tmpb_min = 0;
	
	if (sz3>=3)
	{
		tmpb = p_vmax[2]-p_vmin[2]; tmpb = (tmpb==0)?1:tmpb;
		tmpb_min = p_vmin[2];
	}
	
	if (sz3>=2)
	{
		tmpg = p_vmax[1]-p_vmin[1]; tmpg = (tmpg==0)?1:tmpg;
		tmpg_min = p_vmin[1];
	}
	
	if (sz3>=1)
	{
		tmpr = p_vmax[0]-p_vmin[0]; tmpr = (tmpr==0)?1:tmpr;
		tmpr_min = p_vmin[0];
	}
	
	//the wrong Ctype options should be disabled in the interface instead of a complicated logic management here
	NSUInteger bytesPerRow = sz0 * 4;
	
	switch (ctype)
	{
		case colorRedOnly:
			tg = tb = 0;
			for (j=0;j<sz1;j++)
			{
				for (i=0;i<sz0;i++)
				{
					tr = (bIntensityRescale==NO) ? p4d[0][curpos][j][i] : floor((p4d[0][curpos][j][i]-tmpr_min)/tmpr*255.0);
					tmpData[j * bytesPerRow + i * 4] = tr;
					tmpData[j * bytesPerRow + i * 4 + 1] = tg;
					tmpData[j * bytesPerRow + i * 4 + 2] = tb;
					tmpData[j * bytesPerRow + i * 4 + 3] = 0;
				}
			}
			
			break;
			
		case colorGray: //070716
			for (j=0;j<sz1;j++)
			{
				for (i=0;i<sz0;i++)
				{
					double tmpval=0;
					for (int tmpcnt=0;tmpcnt<sz3;tmpcnt++)
					{
						if (tmpcnt==0)
							tmpval += ((bIntensityRescale==NO) ? p4d[tmpcnt][curpos][j][i] : floor((p4d[tmpcnt][curpos][j][i]-tmpr_min)/tmpr*255.0));
						else if (tmpcnt==1)
							tmpval += ((bIntensityRescale==NO) ? p4d[tmpcnt][curpos][j][i] : floor((p4d[tmpcnt][curpos][j][i]-tmpg_min)/tmpg*255.0));
						else if (tmpcnt==2)
							tmpval += ((bIntensityRescale==NO) ? p4d[tmpcnt][curpos][j][i] : floor((p4d[tmpcnt][curpos][j][i]-tmpb_min)/tmpb*255.0));
						else
							tmpval += ((bIntensityRescale==NO) ? p4d[tmpcnt][curpos][j][i] : p4d[tmpcnt][curpos][j][i]); //in this case, don't about any channel more than 3
					}
					tmpval /= sz3;
					tr = tg = tb = (unsigned char)tmpval;
					tmpData[j * bytesPerRow + i * 4] = tr;
					tmpData[j * bytesPerRow + i * 4 + 1] = tg;
					tmpData[j * bytesPerRow + i * 4 + 2] = tb;
					tmpData[j * bytesPerRow + i * 4 + 3] = 0;
				}
			}
			break;
			
		case colorRed2Gray:
			for (j=0;j<sz1;j++)
			{
				for (i=0;i<sz0;i++)
				{
					tg = tb = tr = (bIntensityRescale==NO) ? p4d[0][curpos][j][i] : floor((p4d[0][curpos][j][i]-tmpr_min)/tmpr*255.0);
					tmpData[j * bytesPerRow + i * 4] = tr;
					tmpData[j * bytesPerRow + i * 4 + 1] = tg;
					tmpData[j * bytesPerRow + i * 4 + 2] = tb;
					tmpData[j * bytesPerRow + i * 4 + 3] = 0;
				}
			}
			break;
			
		case colorGreenOnly:
			tr = tb = 0;
			for (j=0;j<sz1;j++)
			{
				for (i=0;i<sz0;i++)
				{
					tg = (bIntensityRescale==NO) ? p4d[1][curpos][j][i] : floor((p4d[1][curpos][j][i]-tmpg_min)/tmpg*255.0);
					tmpData[j * bytesPerRow + i * 4] = tr;
					tmpData[j * bytesPerRow + i * 4 + 1] = tg;
					tmpData[j * bytesPerRow + i * 4 + 2] = tb;
					tmpData[j * bytesPerRow + i * 4 + 3] = 0;
				}
			}
			break;
			
		case colorGreen2Gray:
			for (j=0;j<sz1;j++)
			{
				for (i=0;i<sz0;i++)
				{
					tr = tb = tg = (bIntensityRescale==NO) ? p4d[1][curpos][j][i] : floor((p4d[1][curpos][j][i]-tmpg_min)/tmpg*255.0);
					//NSUInteger p[4] = {tr, tg, tb, 0};
					//[tmpimg setPixel:p atX:i y:j];
					tmpData[j * bytesPerRow + i * 4] = tr;
					tmpData[j * bytesPerRow + i * 4 + 1] = tg;
					tmpData[j * bytesPerRow + i * 4 + 2] = tb;
					tmpData[j * bytesPerRow + i * 4 + 3] = 0;
				}
			}
			break;
			
		case colorBlueOnly:
			tr = tg = 0;
			for (j=0;j<sz1;j++)
			{
				for (i=0;i<sz0;i++)
				{
					tb = (bIntensityRescale==NO) ? p4d[2][curpos][j][i] : floor((p4d[2][curpos][j][i]-tmpb_min)/tmpb*255.0);
					tmpData[j * bytesPerRow + i * 4] = tr;
					tmpData[j * bytesPerRow + i * 4 + 1] = tg;
					tmpData[j * bytesPerRow + i * 4 + 2] = tb;
					tmpData[j * bytesPerRow + i * 4 + 3] = 0;
				}
			}
			break;
			
		case colorBlue2Gray:
			for (j=0;j<sz1;j++)
			{
				for (i=0;i<sz0;i++)
				{
					tr = tg = tb = (bIntensityRescale==NO) ? p4d[2][curpos][j][i] : floor((p4d[2][curpos][j][i]-tmpb_min)/tmpb*255.0);
					tmpData[j * bytesPerRow + i * 4] = tr;
					tmpData[j * bytesPerRow + i * 4 + 1] = tg;
					tmpData[j * bytesPerRow + i * 4 + 2] = tb;
					tmpData[j * bytesPerRow + i * 4 + 3] = 0;
				}
			}
			break;
			
		case colorRGB:
			for (j=0;j<sz1;j++)
			{
				for (i=0;i<sz0;i++)
				{
					tr = (bIntensityRescale==NO) ? p4d[0][curpos][j][i] : floor((p4d[0][curpos][j][i]-tmpr_min)/tmpr*255.0);
					tg = (bIntensityRescale==NO) ? p4d[1][curpos][j][i] : floor((p4d[1][curpos][j][i]-tmpg_min)/tmpg*255.0);
					tb = (bIntensityRescale==NO) ? p4d[2][curpos][j][i] : floor((p4d[2][curpos][j][i]-tmpb_min)/tmpb*255.0);
					tmpData[j * bytesPerRow + i * 4] = tr;
					tmpData[j * bytesPerRow + i * 4 + 1] = tg;
					tmpData[j * bytesPerRow + i * 4 + 2] = tb;
					tmpData[j * bytesPerRow + i * 4 + 3] = 0;
				}
			}
			break;
			
		case colorRG:
			tb = 0;
			for (j=0;j<sz1;j++)
			{
				for (i=0;i<sz0;i++)
				{
					tr = (bIntensityRescale==NO) ? p4d[0][curpos][j][i] : floor((p4d[0][curpos][j][i]-tmpr_min)/tmpr*255.0);
					tg = (bIntensityRescale==NO) ? p4d[1][curpos][j][i] : floor((p4d[1][curpos][j][i]-tmpg_min)/tmpg*255.0);
					tmpData[j * bytesPerRow + i * 4] = tr;
					tmpData[j * bytesPerRow + i * 4 + 1] = tg;
					tmpData[j * bytesPerRow + i * 4 + 2] = tb;
					tmpData[j * bytesPerRow + i * 4 + 3] = 0;
				}
			}
			break;
			
		case colorUnknown:
		default:
			break;
	}

	//return [tmpimg CGImage];
	
	CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, tmpData, sz0*sz1*4, NULL);
	CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
	CGImageRef tmpimg = CGImageCreate(sz0, sz1, 8, 32, sz0*4, colorSpaceRef, kCGBitmapByteOrderDefault, provider, NULL, NO, kCGRenderingIntentDefault);
	return tmpimg;
	 
	/*
	NSData *imgdata = [NSData dataWithBytes:tmpData length:sz0*sz1*sz2*4];
	[imgdata autorelease];
	UIImage *tmpimg = [[UIImage alloc ] initWithData:imgdata];
	[tmpimg autorelease];
	return [tmpimg CGImage];
	 */
}

@end
